import { Ajax } from './YvanUIAjax';
import { Db } from './YvanUIDb';
import {VJson} from "./YvanModule";
import {CtlBase} from "./CtlBase";

export type FormatterFunction = (id: string) => string;

export type ValidFunction = (value: string) => string | ValidFunction | undefined;

export type ComplexValidFunction = (valid: string, value: string) => string | undefined;

export type ServerJsUrlTransformFunction = (jsUrl: string) => string | undefined;

export type SqlUrlTransformFunction = (jsUrl: string) => string | undefined;

export interface DictItem {
    id: string;
    text: string;

    [id: string]: string;
}

export type Dict = DictItem[];

export declare interface ErrorMsgDataItem {
    /** 错误id 由allData 的__importID__字段值 + "_" + field的值 表示哪一行的哪一列出错，行校验错误时候直接为allData 的__importID__ + "" */
    errorId: string
    /** 对应数据行 allData 的__importID__字段值 */
    importID: number
    /** 字段 */
    field: string
    /** 字段值 */
    title: string
    /** 字段值 */
    value: string
    /** 错误信息 */
    errormessage: string
}

export declare interface ImportResult {
    /** 所有导入的数据，如果有字典会格式化到字典，格式化错误的保持原始值 */
    allData: any[]
    /** 导入正确的数据 */
    okData: any[]
    /** 导入错误的数据 */
    errorData: any[]
    /** 导入错误数据的错误明细 */
    errorMsgData: ErrorMsgDataItem[]
}

/** 定义参数列 */
export declare interface Field {
    /** 字段 */
    field: string
    /** 字段名 */
    title: string
    /** 校验方法，校验通过返回true， 否则返回错误信息 会记录到错误列表里面 errorMsgData */
    validate?: ((v: ValidateObject) => true | string) | string
    /** 格式化，表格显示 */
    formatter?: ((v: any) => any) | string
    /** 导入格式化 返回null或者undefined 表示格式化错误，会记录到错误列表里面 errorMsgData */
    importFormatter?: ((v: ValidateObject) => null | undefined | string | number) | string
    /** 字典， 参与数据校验和表格显示格式化， 校验不通过的，会记录到错误列表里面 errorMsgData */
    data?: any | { id: string | number, text: string }
}

/** 格式化及校验的参数 */
export declare interface ValidateObject {
    field: Field
    ov: any,
    nv: any,
    rowIndex: number,
    data: any,
    rowDatas: any[],
}

/** 行数据校验的参数 */
export declare interface RowValidateObject {
    fields: Field[],
    data: any,
    rowIndex: number,
    rowDatas: any[]
}

/**
 * 定义切口，可以在外部修改数据
 */
export declare type AfterClientValidate =
    ((importResult: ImportResult, resolve: (value?: (ImportResult | PromiseLike<ImportResult> | undefined)) => void) => ImportResult)
    | undefined

/**
 * YvanUI 全局扩展配置
 */
export interface ExtendOption {
    /**
     * 扩展自定义的 vjson 运行时 修改
     */
    beforeResolverVJson: (module:any, vJson: VJson)=> VJson;

    /**
     * 扩展 onLoad方法后执行
     */
    afterModuleRender: (module: any)=> void;

    /**
     * 扩展自定义的 ajax 方法
     */
    ajax: Ajax.Function;

    /**
     * serverJS 请求前缀
     */
    serverJsPrefix: string;

    /**
     * 扩展自定义的数据库
     */
    dbs: { [db: string]: Db.Client };

    /**
     * 扩展全局 formatter 函数
     */
    formatter: { [db: string]: FormatterFunction };

    /**
     * 扩展全局 dict 字典
     */
    dict: { [dictName: string]: Dict };

    /**
     * 扩展全局 校验方法
     */
    validType: { [validName: string]: ValidFunction };

    /**
     * 复杂校验通用方法
     */
    complexValid: { [validName: string]: ComplexValidFunction };

    /**
     * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
     * 可以修改 vjson 的内容，但不能删除他
     */
    componentRenderFilter: (vjson: any) => undefined | boolean

    /**
     * excel导入
     */
    readExcelWithFieldSet: (file: File, fieldSet: any[], dataStartRow: number, titleRowNumber: number,
                                          rowValidate: ((rv: RowValidateObject) => true | string) | undefined,
                                          otherValidate: AfterClientValidate) => Promise<ImportResult>
}

export const version = "3.0.2"

/**
 * 全局 vjson 运行时
 */
export let beforeResolverVJson: (undefined | ((module: any, vJson: VJson)=> VJson)) = undefined;

export let afterModuleRender: (undefined | ((module: any)=>void)) = undefined;

/**
 * 全局 ajax 方法
 */
export let ajax: Ajax.Function;

/**
 * 全局 数据库连接
 */
export const dbs: { [db: string]: Db.Client } = {};

/**
 * 全局 formatter 函数
 */
export const formatter: { [db: string]: FormatterFunction } = {};

/**
 * 全局 dict 字典
 */
export const dict: { [dictName: string]: Dict } = {};

/**
 * 全局 校验方法
 */
export const validType: { [validName: string]: ValidFunction } = {};

/**
 * 复杂校验通用方法
 */
export const complexValid: { [validName: string]: ComplexValidFunction } = {};

/**
 * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
 * 可以修改 vjson 的内容，但不能删除他
 */
export let componentRenderFilter: (undefined | ((vjson: any) => undefined | boolean)) = undefined;

export let readExcelWithFieldSet: (undefined | ( (file: File, fieldSet: any[], dataStartRow: number, titleRowNumber: number,
                                   rowValidate: ((rv: RowValidateObject) => true | string) | undefined,
                                   otherValidate: AfterClientValidate) => Promise<ImportResult>)) = undefined

export function getServerPrefix(url: string) {
    return _.get(window, '_YvanUI_serverJSPrefix') + url;
}

/**
 * YvanUI 全局扩展配置
 * @param option 配置信息
 */
export function extend(option: Partial<ExtendOption>) {
    if (option.beforeResolverVJson) {
        beforeResolverVJson = option.beforeResolverVJson
    }

    if (option.afterModuleRender) {
        afterModuleRender = option.afterModuleRender;
    }

    if (option.ajax) {
        ajax = option.ajax
    }

    if (option.serverJsPrefix) {
        _.extend(window, { _YvanUI_serverJSPrefix: option.serverJsPrefix });
    }

    if (option.dbs) {
        _.extend(dbs, option.dbs);
    }

    if (option.dict) {
        _.extend(dict, option.dict);
    }

    if (option.validType) {
        _.extend(validType, option.validType);
    }

    if (option.formatter) {
        _.extend(formatter, option.formatter);
    }

    if (option.complexValid) {
        _.extend(complexValid, option.complexValid);
    }

    if (option.componentRenderFilter) {
        componentRenderFilter = option.componentRenderFilter
    }

    if (option.readExcelWithFieldSet) {
        readExcelWithFieldSet = option.readExcelWithFieldSet
    }
}
